home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / semantics.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  16KB  |  579 lines

  1. /*
  2.  * @(#)semantics.c    1.10  10/24/89
  3.  */
  4. #include "assert.h"
  5. #include "scan.h"
  6. #include "nodes.h"
  7. #include "error.h"
  8. #include "opNames.h"
  9. #include "flags.h"
  10. #include "system.h"
  11. #include "trace.h"
  12. #include "option.h"
  13. #include "builtins.h"
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <sys/param.h>
  17. #include <sys/file.h>
  18. #include <a.out.h>
  19. #include <errno.h>
  20. #undef NULL
  21. #include "ndbm.h"
  22. #undef NULL
  23. #define NULL 0
  24.  
  25. extern char *emDirectory, *emdbDirectory;
  26.  
  27. static struct {
  28.   Boolean          shouldDo;
  29.   int             verboseLevel;
  30.   char            *name;
  31. } treePasses[] = { 
  32.   TRUE , 1, "parsing",
  33.   TRUE , 1, "removing sugar",
  34.   TRUE , 1, "processing symbols",
  35.   TRUE , 1, "doing imports",
  36.   TRUE , 1, "doing manifests",
  37.   TRUE , 1, "assigning types",
  38.   TRUE , 1, "checking types",
  39.   TRUE , 1, "inline detection",
  40.   FALSE, 0, "figuring concrete types",
  41.   FALSE, 0, "figuring locals",
  42.   TRUE , 1, "doing exports",
  43.   FALSE, 0, "code generation",
  44.   0, 0, 0};
  45.  
  46. extern void removeSugar(), processSymbols(), doManifest(),
  47.         DisplayTree(), assignTypes(), typeCheck(), detectInlines(),
  48.         multiPassManifest(), doSymbolGraph(),
  49.         doKnowCTs(), doKnowManifests(),
  50.         doKnowLocals(), newAssignTypes();
  51.  
  52. extern char *makeOIDDotoFileName();
  53.  
  54. char workingDirectory[MAXPATHLEN];
  55. #define MAXDOTSFILES 100
  56. typedef struct sDotsRec {
  57.   Boolean         alreadyGenerated;
  58.   int             codeFileNumber;
  59.   OID              codeOID;
  60.   OID             createdOID;
  61. } DotsRec, *DotsRecPtr;
  62.  
  63. DotsRec dotsFiles[MAXDOTSFILES];
  64. static int nextDotsFile = 0;
  65.  
  66. static void doTree(name, fTreeFile, Root)
  67. char *name;
  68. FILE *fTreeFile;
  69. NodePtr Root;
  70. {
  71.   register int stage;
  72.   for (stage = 0; 
  73.        treePasses[stage].name && strcmp(name, treePasses[stage].name);
  74.        stage++) ;
  75.   assert(treePasses[stage].name != NULL);
  76.   if (treePasses[stage].shouldDo) {
  77.     if (tflag) {
  78.       TRACE0(passes, 1, "Writing the tree file.");
  79.       fprintf(fTreeFile, "After %s\n", treePasses[stage].name);
  80.       DisplayTree(fTreeFile, Root, treePasses[stage].verboseLevel, 9999);
  81.     }
  82.   }
  83. }
  84.  
  85. extern NodePtr readTree();
  86. void doExports(), doImports(), generateCode();
  87.  
  88. extern int nextObjectNumber;
  89.  
  90. FILE *treeFile = NULL;
  91. FILE *codeFile = NULL;
  92. char *codeFileName = NULL, *codeFileRoot;
  93.  
  94. /*
  95.  * Call the program named f with the arguments v, and stdin and out
  96.  * directed to inf and outf respectively.
  97.  */
  98. #include <sys/wait.h>
  99.  
  100. int callsys(f, v, inf, outf)
  101. char *f, **v, *inf, *outf;
  102. {
  103.   int t;
  104.   union wait status;
  105.   register char **cpp;
  106.   
  107.   IFTRACE(passes, 5) {
  108.     fprintf(stdout, "%s:", f);
  109.     for (cpp = v; *cpp != 0; cpp++) fprintf(stdout, " %s", *cpp);
  110.     if (inf != NULL) fprintf(stdout, " < %s", inf);
  111.     if (outf != NULL) fprintf(stdout, " > %s", outf);
  112.     fprintf(stdout, "\n");
  113.   }
  114.   t = vfork();
  115.   if (t == -1) {
  116.     fprintf(stderr, "No more processes\n");
  117.     return (100);
  118.   }
  119.   if (t == 0) {        /* I am the child */
  120.     int infd, outfd;
  121.     if (inf != NULL) {
  122.       infd = open(inf, O_RDONLY, 0666);
  123.       (void) dup2(infd, 0);
  124.     }
  125.     if (outf != NULL) {
  126.       outfd = open(outf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  127.       (void) dup2(outfd, 1);
  128.     }
  129.     execv(f, v);
  130.     fprintf(stderr, "Can't find %s\n", f);
  131.     (void) fflush(stderr);
  132.     _exit(100);
  133.   }
  134.   while (t != wait(&status))
  135.     ;
  136.   if ((t=status.w_termsig) != 0 && t!=14) {
  137.     if (t!=2) {
  138.       fprintf(stderr, "Fatal error in %s\n", f);
  139.     }
  140.   }
  141.   return (status.w_retcode);
  142. }
  143.  
  144. extern int link(), symlink();
  145.  
  146. void myLink(existing, new, symbolic, Root)
  147. char *existing, *new;
  148. Boolean symbolic;
  149. NodePtr Root;
  150. {
  151.   int (*linkroutine)()  = symbolic ? symlink : link;
  152.   char *linkroutinename = symbolic ? "symlink" : "link";
  153.  
  154.   if ((*linkroutine)(existing, new) < 0) {
  155.     if (errno == EEXIST) {
  156.       if (unlink(new) < 0) { 
  157.     ErrorMessage(Root, "Cannot unlink %s: %s", new,
  158.       errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  159.       } else {
  160.     if ((*linkroutine)(existing, new) < 0) {
  161.       ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new,
  162.         existing,
  163.         errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  164.     }
  165.       }
  166.     } else {
  167.       ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new, existing,
  168.     errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  169.     }
  170.   }
  171. }
  172.  
  173. static int finishedPass;
  174. #define TOTALPASSES 14
  175.  
  176. void checkCompletion()
  177. {
  178.   if (! Cflag) return;
  179.   if (Cvalue <= 0 && TOTALPASSES + Cvalue <= finishedPass) exit(0);
  180.   else if (Cvalue > 0 && finishedPass >= Cvalue) exit(0);
  181. }
  182. extern void initializeOwnStuff();
  183.  
  184. void DoneParsing(Root)
  185. NodePtr Root;
  186. {
  187.   char *treeFileName, *p;
  188.   char *realDotoFileName, *createdDotoFileName;
  189.   char **systemBuffer, **execvec;
  190.   char binpath[100];
  191.   int systemResult, i;
  192.   FILE *dotgFile;
  193.  
  194.   CheckForErrors();
  195.  
  196.   if (!strcmp(currentFileName, "<stdin>")) {
  197.     codeFileRoot = malloc(6);
  198.     strcpy(codeFileRoot, "stdin");
  199.   } else {
  200.     for (p = currentFileName; *p; p++) ;
  201.     for (p--; *p != '/' && p >= currentFileName; p--) ;
  202.     if (*p == '/') p++; else p = currentFileName;
  203.     codeFileRoot = (char  *) malloc((unsigned)strlen(p) + 1);
  204.     strcpy(codeFileRoot, p);
  205.     for (p = codeFileRoot; *p; p++) ;
  206.     for (p--; *p != '.'; --p) ;
  207.     if (p > codeFileRoot) *p = '\0';
  208.   }
  209.   if (tflag) {
  210.     treeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 6);
  211.     (void) strcpy(treeFileName, codeFileRoot);
  212.     (void) strcat(treeFileName, ".tree");
  213.     treeFile = fopen(treeFileName, "w");
  214.     if (treeFile == NULL) {
  215.       fprintf(stderr, "Can't open the tree file (%s).\n", treeFileName);
  216.       exit (1);
  217.     }
  218.     free(treeFileName);
  219.   }
  220.  
  221.   doTree("parsing", treeFile, Root);
  222.   finishedPass = 1;
  223.   checkCompletion();
  224.  
  225.   TRACE0(passes, 1, "Removing sugar.");
  226.   removeSugar(&Root);
  227.   doTree("removing sugar", treeFile, Root);
  228.   CheckForErrors();
  229.   finishedPass = 2;
  230.   checkCompletion();
  231.  
  232.   TRACE0(passes, 1, "Resolving symbols.");
  233.   processSymbols(Root);
  234.   doTree("processing symbols", treeFile, Root);
  235.   CheckForErrors();
  236.   finishedPass = 3;
  237.   checkCompletion();
  238.  
  239.   TRACE0(passes, 1, "Doing imports.");
  240.   doImports(Root);
  241.   doTree("doing imports", treeFile, Root);
  242.   CheckForErrors();
  243.   finishedPass = 4;
  244.   checkCompletion();
  245.  
  246.   initializeOwnStuff();
  247.  
  248.   TRACE0(passes, 1, "Doing manifests.");
  249.   doKnowManifests(Root);
  250.   doTree("doing manifests", treeFile, Root);
  251.   CheckForErrors();
  252.   finishedPass = 5;
  253.   checkCompletion();
  254.  
  255.   
  256.   TRACE0(passes, 1, "Assigning types.");
  257.   newAssignTypes(Root, 9999);
  258.   doTree("assigning types", treeFile, Root);
  259.   CheckForErrors();
  260.   finishedPass = 6;
  261.   checkCompletion();
  262.  
  263.   if (! loadedDummyBuiltins) {
  264.     TRACE0(passes, 1, "Checking the types.");
  265.     typeCheck(Root);
  266.     doTree("checking types", treeFile, Root);
  267.     CheckForErrors();
  268.   }
  269.   finishedPass = 7;
  270.   checkCompletion();
  271.  
  272.   if (cflag && !bflag) return;
  273.  
  274.   /*
  275.    * Inlineable routines and signal and continue detection.
  276.    */
  277.   TRACE0(passes, 1, "Inline detection.");
  278.   detectInlines(Root);
  279.   doTree("inline detection", treeFile, Root);
  280.   CheckForErrors();
  281.   finishedPass = 8;
  282.   checkCompletion();
  283.   
  284.   doSymbolGraph(Root);
  285.   
  286.   if (OPTION(knowct, 1) && !loadedDummyBuiltins) {
  287.     TRACE0(passes, 1, "Figuring out Concrete Types.");
  288.     doKnowCTs(Root);
  289.     doTree("figuring concrete types", treeFile, Root);
  290.     CheckForErrors();
  291.     finishedPass = 9;
  292.     checkCompletion();
  293.   }
  294.  
  295.   if (OPTION(locals, 1) && !loadedDummyBuiltins) {
  296.     TRACE0(passes, 1, "Figuring out Locals.");
  297.     doKnowLocals(Root);
  298.     doTree("figuring locals", treeFile, Root);
  299.     CheckForErrors();
  300.     finishedPass = 10;
  301.     checkCompletion();
  302.   }
  303.  
  304.   TRACE0(passes, 1, "Doing exports.");
  305.   doExports(Root);
  306.   doTree("doing exports", treeFile, Root);
  307.   CheckForErrors();
  308.   finishedPass = 11;
  309.   checkCompletion();
  310.  
  311.   if (cflag) return;
  312.  
  313.   TRACE0(passes, 1, "Code generation.");
  314.   codeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 16);
  315.  
  316.   generateCode(Root);
  317.   doTree("code generation", treeFile, Root);
  318.   free(codeFileName);
  319.   if (codeFile != NULL && fclose(codeFile) == EOF) assert(FALSE);
  320.   CheckForErrors();
  321.   finishedPass = 12;
  322.   checkCompletion();
  323.  
  324.   systemBuffer = (char **) malloc((unsigned) 6 * sizeof(char *));
  325.   systemBuffer[1] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
  326.   systemBuffer[5] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
  327.  
  328.   systemBuffer[0] = "as";
  329.   systemBuffer[2] = "-o";
  330.   systemBuffer[3] = (char *) NULL;
  331.   systemBuffer[4] = (char *) NULL;
  332.  
  333.   TRACE0(passes, 1, "Assembling.");
  334.   assert(nextObjectNumber == nextDotsFile);
  335.   for (i = 0; i < nextDotsFile; i++) {
  336.     TRACE5(doto, 3,
  337.       "i=%d alreadyGenerated=%s codeFileNumber=%d codeOID=0x%08x createdOID=0x%08x",
  338.       i, dotsFiles[i].alreadyGenerated ? "true" : "false", 
  339.       dotsFiles[i].codeFileNumber, dotsFiles[i].codeOID,
  340.       dotsFiles[i].createdOID);
  341.     sprintf(systemBuffer[5], "%s.%d.o", codeFileRoot, i);
  342.     realDotoFileName = makeOIDDotoFileName(dotsFiles[i].codeOID);
  343.     if (! dotsFiles[i].alreadyGenerated) {
  344.       sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
  345.       systemBuffer[3] = realDotoFileName;
  346.       systemResult =
  347.     callsys("/bin/as", systemBuffer, (char *)NULL, (char *)NULL);
  348.       if (systemResult != 0) {
  349.     ErrorMessage(Root, "As error");
  350.       } else {
  351.     if (dotsFiles[i].createdOID != 0) {
  352.       /* we need to link the other name to the original name */
  353.       createdDotoFileName = makeOIDDotoFileName(dotsFiles[i].createdOID);
  354.       myLink(realDotoFileName, createdDotoFileName, FALSE, Root);
  355.       free(createdDotoFileName);
  356.     }
  357. #ifdef sun
  358.     /* we need to fix the header */
  359.     {
  360.       int inf;
  361.       struct exec header;
  362.       inf = open(realDotoFileName, O_RDWR, 0);
  363.       assert(inf != NULL);
  364.       if (read(inf, &header, sizeof(header)) != sizeof(header)) 
  365.         assert(FALSE);
  366. #define CHECK(S) if (!(S)) assert(FALSE);
  367.       CHECK(header.a_text != 0);
  368.       CHECK(header.a_data == 0);
  369.       CHECK(header.a_drsize == 0);
  370.       header.a_data = header.a_text;
  371.       header.a_drsize = header.a_trsize;
  372.       header.a_text = 0;
  373.       header.a_trsize = 0;
  374.       if (lseek(inf, 0L, 0) < 0) assert(FALSE);
  375.       if (write(inf, &header, sizeof(header)) != sizeof(header)) assert(FALSE);
  376.       (void) close(inf);
  377.     }
  378. #endif
  379.       }
  380.     }
  381.     if (zflag) myLink(realDotoFileName, systemBuffer[5], TRUE, Root);
  382.     free(realDotoFileName);
  383.   }
  384.   CheckForErrors();
  385.  
  386.   if (!zflag) {
  387.     for (i = 0; i < nextObjectNumber; i++) {
  388.       if (dotsFiles[i].alreadyGenerated) continue;
  389.       sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
  390.       systemResult = unlink(systemBuffer[1]);
  391.       if (systemResult < 0) {
  392.     ErrorMessage(Root, "Cannot unlink %s: %s", systemBuffer[1],
  393.       errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  394.       }
  395.     }
  396.   }
  397.   
  398.   sprintf(systemBuffer[1], "%s.g", codeFileRoot);
  399.   if ((dotgFile = fopen(systemBuffer[1], "w")) == NULL) {
  400.     ErrorMessage(Root, "Cannot create %s", systemBuffer[1]);
  401.   } else {
  402.     struct stat st;
  403.     DBM *dotgDBM;
  404.     char dotgDBMName[1024];
  405.     datum keydatum, valuedatum;
  406.     fprintf(dotgFile, "#!%sbin/re\n", emDirectory);
  407.     fprintf(dotgFile, "0x%08xzzzzzz\n", dotsFiles[0].codeOID);
  408.     fstat(fileno(dotgFile), &st);
  409.     fchmod(fileno(dotgFile), st.st_mode | 0111);
  410.     fclose(dotgFile);
  411.     sprintf(dotgDBMName, "%s/DB/dotgdb", emdbDirectory);
  412.     if ((dotgDBM = dbm_open(dotgDBMName, O_RDWR | O_CREAT, 0777)) <= 0) {
  413.       ErrorMessage(Root, "Can't open the data base file %s\n", dotgDBMName);
  414.     } else {
  415.       if (getwd(dotgDBMName) == 0) {
  416.     ErrorMessage(Root, "Can't determine the current directory: %s\n",
  417.       dotgDBMName);
  418.       } else {
  419.     keydatum.dptr = dotgDBMName;
  420.     keydatum.dsize = strlen(dotgDBMName) + 1;
  421.     valuedatum.dptr = "x";
  422.     valuedatum.dsize = 2;
  423.     if (dbm_store(dotgDBM, keydatum, valuedatum, DBM_REPLACE) < 0) {
  424.       ErrorMessage(Root, "Can't write to .g filename database");
  425.     }
  426.       }
  427.       dbm_close(dotgDBM);
  428.     }
  429.   }
  430.  
  431.   finishedPass = 13;
  432.   checkCompletion();
  433.  
  434.   TRACE0(passes, 1, "Invoking the kernel.");
  435.   execvec = (char **) malloc(10 * sizeof(char *));
  436.   execvec[0] = "runec";
  437.   i = 1;
  438.   if (vflag) execvec[i++] = "-v";
  439.   if (iflag) execvec[i++] = "-i";
  440.   if (mflag) {
  441.     execvec[i++] = "-m";
  442.     execvec[i++] = mdata;
  443.   }
  444.   execvec[i++] = systemBuffer[1];
  445.   execvec[i] = (char *) 0;
  446.  
  447.   sprintf(binpath, "%s/bin/runec", emDirectory);
  448.   execv(binpath, execvec);
  449.   assert(FALSE);
  450.  
  451.   CheckForErrors();
  452.   finishedPass = 14;
  453.   checkCompletion();
  454.  
  455.   free(systemBuffer[1]);
  456.   free(systemBuffer[7]);
  457.   free(codeFileRoot);
  458. }
  459.  
  460. void nextCodeFileName()
  461. {
  462.   if (codeFile != NULL) {
  463.     if (fclose(codeFile) == EOF) assert(FALSE);
  464.     codeFile = NULL;
  465.   }
  466.   sprintf(codeFileName, "%s.%d.s", codeFileRoot, nextObjectNumber);
  467. }
  468.  
  469. extern Boolean doGenerateCode, environmentWasImported();
  470.  
  471. /*
  472.  * This one either:
  473.  *   1.  returns TRUE
  474.  *   2.  returns FALSE,opens the codeFile for .s writing
  475.  * In either case it fills in the dotsFiles structure so that we can do the
  476.  * right thing later.
  477.  */
  478. Boolean easyGenerateObject(obj, fCodeOID, fOID)
  479. NodePtr obj;
  480. OID fCodeOID, fOID;
  481. {
  482.   char *realDotoFileName;
  483.   static Boolean theAnswer;
  484.   struct stat statbuf;
  485.   int sysresult;
  486.  
  487.   if (doGenerateCode) return(theAnswer);
  488.   if (nextDotsFile >= MAXDOTSFILES) {
  489.     fprintf(stderr, "Too many output code files.\n");
  490.   }
  491.   assert(fCodeOID != 0);
  492.   if (bflag) {
  493.     if (environmentWasImported(fCodeOID)) {
  494.       theAnswer = TRUE;
  495.     } else {
  496.       theAnswer = FALSE;
  497.     }
  498.   } else {
  499.     realDotoFileName = makeOIDDotoFileName(fCodeOID);
  500.     theAnswer = TRUE;
  501.     sysresult = stat(realDotoFileName, &statbuf);
  502.     if (sysresult < 0) {
  503.       if (errno == ENOENT) theAnswer = FALSE;
  504.       else {
  505.     ErrorMessage(obj, "Cannot stat %s: %s", realDotoFileName,
  506.       errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  507.       }
  508.     }
  509.     free(realDotoFileName);
  510.   }
  511.   dotsFiles[nextDotsFile].alreadyGenerated = theAnswer;
  512.   dotsFiles[nextDotsFile].codeFileNumber = nextObjectNumber;
  513.   dotsFiles[nextDotsFile].codeOID = fCodeOID;
  514.   dotsFiles[nextDotsFile].createdOID = fOID;
  515.   TRACE4(doto, 1,
  516.     "\"%s\" %s code=0x%08x created=0x%08x",
  517.     obj && (obj->tag == P_OBLIT || obj->tag == P_ATLIT) ? 
  518.       ST_SymbolName(obj->b.oblit.name->b.symdef.symbol) : "<?>",
  519.     dotsFiles[nextDotsFile].alreadyGenerated ? "AG" : "!AG", 
  520.     dotsFiles[nextDotsFile].codeOID,
  521.     dotsFiles[nextDotsFile].createdOID);
  522.   nextDotsFile++;
  523.   nextCodeFileName();
  524.   if (! theAnswer) {
  525.     codeFile = fopen(codeFileName, "w");
  526.     if (codeFile == NULL) {
  527.       fprintf(stderr, "Can't open the code file (%s).\n", codeFileName);
  528.       exit (1);
  529.     }
  530.   }
  531.   return(theAnswer);
  532. }
  533.  
  534. extern void init_Sugar();
  535. extern void initializebuildATs();
  536. extern void initializeGenerate();
  537. extern void initializeAllocate();
  538. extern void initializeSymbols();
  539. extern void initializeSymbolTable();
  540. extern void initializeEnvironment();
  541. extern void initializeManifest();
  542. extern void initializeTrace();
  543. extern void initializeOption();
  544. extern void initializeGraphs();
  545. extern void initializeKnowCT();
  546. extern void initializeKnowManifest();
  547. extern void initializeKnowLocal();
  548. extern void Scanner_Initialize();
  549. extern void initializeNodes();
  550.  
  551. void initialize()
  552. {
  553.   initializeDataBaseFiles();
  554.   initializeNodes();
  555.   ON_initialize();
  556.   init_Conforms();
  557.   init_Sugar();
  558.   initializebuildATs();
  559.   initializeAllocate();
  560.   initializeGenerate();
  561.   initializeSymbols();
  562.   initializeSymbolTable();
  563.   initializeEnvironment();
  564.   initializeManifest();
  565.   initializeRegisters();
  566.   initializeTrace();
  567.   initializeOption();
  568.   initializeGraphs();
  569.   initializeKnowCT();
  570.   initializeKnowManifest();
  571.   initializeKnowLocal();
  572.   Scanner_Initialize();
  573. }
  574.  
  575. void Finalize()
  576. {
  577.   ON_finalize();
  578. }
  579.